/**
 * @Author       : Hejh(3010733382@qq.com)
 * @Version      : V1.0
 * @Date         : 2024-01-11 16:48:13
 * @Description  : 响应式配置文件
 */

let activeEffect = undefined //当前副作用
const effectStack = [] // 副作用栈

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 副作用函数找到依赖的key（对象的键值）--->对于的副作用数组，将自己清除
 * @param {Function} fn 副作用函数
 */
const cleanup = (fn) => {
  fn.deps.forEach((dep) => {
    dep.delete(fn)
  })
  fn.deps.length = 0
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 对副作用函数进行增强，便于响应式data get时收集副作用函数
 * @param {*} fn 副作用函数
 */
const effect = (fn) => {
  // 对fn进行二次增强
  // 初次和更新都会执行代码
  const effectFn = () => {
    cleanup(effectFn)
    effectStack.push(effectFn)
    activeEffect = effectFn
    fn()
    effectStack.pop()
    activeEffect = effectStack[effectStack.length - 1]
  }
  // 初次执行代码
  effectFn.deps = []
  effectFn()
}

const bucket = new WeakMap() // 存储data--->副作用的映射

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 创建一个响应式数据
 * @param {*} data 原始数据
 */
const createReactive = (data) => {
  const obj = new Proxy(data, {
    get(target, key) {
      if (!activeEffect) {
        return target[key]
      }
      // 获取target对应的key--effects映射表
      let depsMap = bucket.get(target)
      if (!depsMap) {
        depsMap = new Map()
        bucket.set(target, depsMap)
      }

      let deps = depsMap.get(key)
      if (!deps) {
        deps = new Set()
        depsMap.set(key, deps)
      }
      deps.add(activeEffect)
      activeEffect.deps.push(deps)
      return target[key]
    },

    set(target, key, value) {
      target[key] = value
      let depsMap = bucket.get(target)
      if (!depsMap) {
        return true
      }
      let effects = depsMap.get(key)
      // 避免无限制循环
      let effectsToRun = new Set(effects)
      effectsToRun &&
        effectsToRun.forEach((e) => {
          if (e !== activeEffect) {
            e()
          }
        })
      return true
    }
  })
  return obj
}

module.exports = {
  createReactive,
  effect
}
